(function () {
	var lastTime = 0;
	var vendors = ['ms', 'moz', 'webkit', 'o'];
	for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
		window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
		window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] || window[vendors[x] + 'CancelRequestAnimationFrame'];
	}

	if (!window.requestAnimationFrame)
		window.requestAnimationFrame = function (callback, element) {
			var currTime = new Date().getTime();
			var timeToCall = Math.max(0, 16 - (currTime - lastTime));
			var id = window.setTimeout(function () {
				callback(currTime + timeToCall);
			}, timeToCall);
			lastTime = currTime + timeToCall;
			return id;
		};

	if (!window.cancelAnimationFrame)
		window.cancelAnimationFrame = function (id) {
			clearTimeout(id);
		};
})();

var sys = (function () {
	var _this;
	var s = function () {
		_this = this;
	};
	s.prototype.init = function () {
		this.stopScrolling();
		this.loadCompant = false;
	};
	s.prototype.lazyLoad = function (obj, fun) {
		var imgArr = [];
		$(obj)
			.find('*')
			.each(function () {
				let $this = $(this);
				var src = $this.attr('data-src');
				!!!src && (src = $this.attr('src'));

				if (src) {
					if (!$this.hasClass('lazy')) {
						imgArr.push({ src, dom: this });
						$this.attr('data-src', '');
						$this.removeAttr('data-src');
						if ($this.hasClass('background_100') || $this.hasClass('background')) {
							$this.css('background-image', `url(${src})`);
						} else {
							$this.attr('src', src);
						}
					}
				} else {
					var img = $this.css('background-image');
					if (img != 'none') {
						img = img.replace(/("|'|\(|\)|url)/g, '').toString();
						imgArr.push({ src: img, dom: this });
					}
				}
			});

		let imgArrNum = imgArr.length;
		$('.loadingLine').show();
		let promises = Array.from(
			{ length: imgArrNum },
			(k, i) => () =>
				new Promise((resolve) => {
					let img = new Image();
					img.src = imgArr[i].src;
					img.onload = () => {
						let cdom = imgArr[i].dom;
						if ($(cdom).hasClass('ir')) {
							cdom.style.width = img.width + 'rem';
							cdom.style.height = img.height + 'rem';
						}
						// console.log('img', img.width, img.height);
						resolve();
					};
					img.onerror = resolve;
				})
		);

		//TODO
		// if (getQueryString('test') == 1) {
		// 	promises.push(
		// 		() =>
		// 			new Promise((resolve) => {
		// 				window.setTimeout(() => {
		// 					resolve();
		// 				}, 5000);
		// 			})
		// 	);
		// }
		promises
			.reduce(
				(previousPromise, nextPromise, idx) =>
					previousPromise.then((img) => {
						return nextPromise().then(() => {
							let d = 100;
							let pp = parseInt(((idx + 1) / imgArrNum) * 100);
							pp = ((pp / 100) * d).toFixed(0);
							$('.loadingLine>div').css('width', pp + '%');
							$('#progress_txt').text(pp + '%');
							// console.log('loading->progress=' + pp);
						});
					}),
				Promise.resolve()
			)
			.then(() => {
				typeof fun == 'function' && fun();
				console.log('sys.lazyLoad finished...');
			});
	};
	s.prototype.stopScrolling = function (e) {
		document.addEventListener('touchmove', _this.preventDefault, { passive: false });
	};
	s.prototype.openScrolling = function () {
		document.removeEventListener('touchmove', _this.preventDefault);
	};
	s.prototype.preventDefault = function (e) {
		e.preventDefault();
	};
	s.prototype.loadingComplete = function () {
		app.loading = false;
		this.init();
	};
	return new s();
})();

//音频控制
var media = (function () {
	var musicUrl = sysParam.musicUrl, //音频连接
		musicPlayIco = sysParam.baseUrl + 'images/mPlay.png', //播放按钮
		musicPauseIco = sysParam.baseUrl + 'images/mPaused.png'; //暂停按钮
	if (getQueryString('music') == 0) {
		musicUrl = null;
	}
	if (musicUrl) {
		var img = "<img src='" + musicPlayIco + "' id='musicCtrl' class='btn mAnim mRb'>";
		$('#app').append(img);
		var m = function () {
			this.audio = new Audio();
			this.audio.setAttribute('autoplay', 'autoplay');
			this.audio.setAttribute('loop', 'loop');
			if (sysParam.musicUrl) {
				this.init();
			}
		};
		m.prototype.init = function () {
			var _this = this;
			this.audio.src = musicUrl;
			this.music = $('#musicCtrl');
			this.music.show();
			this.music.attr('src', musicPlayIco);
			document.onreadystatechange = function () {
				if (document.readyState == 'complete' && _this.audio.paused) {
					_this.audioPlay();
				}
			};
			document.addEventListener('visibilitychange', function () {
				if (document.visibilityState === 'hidden') {
					media.hidden();
				}
				if (document.visibilityState === 'visible' && media.playing) {
					media.audioPlay();
				}
			});
			$('body').one('touchstart', function () {
				_this.audioPlay();
			});
			document.addEventListener(
				'WeixinJSBridgeReady',
				function () {
					_this.audioPlay();
				},
				false
			);
			$('body').on('click', '#musicCtrl', function () {
				_this.musicCtrl(_this);
			});
		};
		m.prototype.musicCtrl = function (b) {
			if (b.audio.paused) {
				b.audioPlay();
				return;
			}
			b.audioPause();
		};
		m.prototype.audioPlay = function () {
			this.music = $('#musicCtrl');
			this.audio.play();
			this.playing = true;
			this.music.attr('src', musicPlayIco);
			this.music.addClass('mAnim');
			console.log('play audio...');
		};
		m.prototype.changeMusic = function (url) {
			if (this.audio.src != url) {
				this.audio.pause();
				this.audio.src = url;
				this.audio.play();
			}
		};
		m.prototype.hidden = function () {
			this.music = $('#musicCtrl');
			this.audio.pause();
			this.music.attr('src', musicPauseIco);
			this.music.removeClass('mAnim');
		};

		m.prototype.audioPause = function () {
			this.playing = false;
			this.hidden();
		};

		m.prototype.isPlaying = function () {
			return this.playing;
		};

		m.prototype.setVolume = function (volume) {
			this.audio.volume = volume ?? 1;
		};

		return new m();
	}
})();

function ajax_img(b) {
	app.ajaxLoading = true;
	return new Promise((resolve, reject) => {
		let url = b.url + window.location.search;
		$.ajax({
			type: b.type ? b.type : 'post',
			url,
			contentType: false,
			processData: false,
			dataType: 'json',
			data: b.data ? b.data : {},
			timeout: 15000,
			success: function (_data) {
				app.ajaxLoading = false;
				let data = _data || {};
				let result_code = data.result_code || -1;
				console.log(`success by result_code==${result_code}: req ${b.url} response data = `, data);
				result_code == 1 ? resolve(data) : reject(data);
			},
			error: function () {
				app.ajaxLoading = false;
				reject({ result_code: 0, result_msg: '网络超时，请刷新后再试！' });
			},
		});
	});
}

function ajax(b) {
	app.ajaxLoading = true;
	return new Promise((resolve, reject) => {
		let url = b.url + window.location.search;
		$.ajax({
			type: b.type ? b.type : 'post',
			url,
			dataType: 'json',
			data: b.data ? b.data : {},
			timeout: 30000,
			success: function (data) {
				app.ajaxLoading = false;
				console.log(`success by result_code==${data.result_code}: req ${b.url} response data = `, data);
				if (b?.resolve == 1) {
					resolve(data);
				} else {
					data.result_code == 1 ? resolve(data) : reject(data);
				}
			},
			error: function () {
				app.ajaxLoading = false;
				reject({ result_code: 0, result_msg: '网络超时，请刷新后再试！' });
			},
		});
	});
}

function ajax_noloading(b) {
	return new Promise((resolve, reject) => {
		let url = b.url + window.location.search;
		$.ajax({
			type: b.type ? b.type : 'post',
			url,
			dataType: 'json',
			data: b.data ? b.data : {},
			timeout: 30000,
			success: function (data) {
				console.log(`success by result_code==${data.result_code}: req ${b.url} response data = `, data);
				data.result_code == 1 ? resolve(data) : reject(data);
			},
			error: function () {
				reject({ result_code: 0, result_msg: '网络超时，请刷新后再试！' });
			},
		});
	});
}

(function () {
	let mlCla = ``;
	let mtCla = ``;
	let delayCla = ``;
	let durationCla = ``;
	let fontsizeCla = ``;
	for (let start = 5; start <= 300; start += 5) {
		mlCla += `.ml_${start}{ margin-left: ${start}rem; }`;
		mtCla += `.mt_${start}{ margin-top: ${start}rem; }`;
	}
	for (let start = 200; start <= 5000; start += 50) {
		delayCla += `.delay_${start}{ animation-delay: ${start / 1000}s;-webkit-animation-delay: ${start / 1000}s; }`;
	}
	for (let start = 500; start <= 5000; start += 500) {
		durationCla += `.duration_${start}{ animation-duration: ${start / 1000}s;-webkit-animation-duration: ${start / 1000}s; }`;
	}
	for (let start = 14; start <= 100; start += 1) {
		fontsizeCla += `.fontsize_${start}{ font-size: ${start}rem; }`;
	}
	if (document.all) {
		console.log('document.all');
		window.style = `${mlCla}${mtCla}${delayCla}${durationCla}${fontsizeCla}`;
		document.createStyleSheet('javascript:style');
	} else {
		var style = document.createElement('style');
		style.type = 'text/css';
		style.innerHTML = `${mlCla}${mtCla}${delayCla}${durationCla}${fontsizeCla}`;
		document.getElementsByTagName('HEAD').item(0).appendChild(style);
	}
})();

function lazyLoad(className, cb) {
	let srcs = [];
	$(className).each(function () {
		let $this = $(this);
		let dataSrc = $this.attr('data-src');
		dataSrc = dataSrc || $this.attr('src');
		if (!!dataSrc) {
			srcs.push({ src: dataSrc, dom: this });
		}
		if (this.nodeName.toLowerCase() === 'div' || this.nodeName.toLowerCase() === 'span') {
			$this.css('background-image', `url(${dataSrc})`);
			$this.css('-webkit-background-image', `url(${dataSrc})`);
		} else {
			$this.attr('src', dataSrc);
		}

		$this.removeClass('lazy');
		$this.removeAttr('data-src');
	});
	// app.ajaxLoading = true;
	imgLoaded(srcs, () => {
		// app.ajaxLoading = false;
		cb();
	});
}

function imgLoaded(srcArr = [], cb) {
	let loadedNum = 0;
	let doing = function () {
		loadedNum++;
		if (loadedNum === srcArr.length && !!cb && Object.prototype.toString.call(cb) === '[object Function]') {
			// console.log(`################ imgLoaded success execute cb() by (${JSON.stringify(srcArr)}) imgs.length=${srcArr.length}`);
			console.log(`################ imgLoaded success execute cb() imgs.length=${srcArr.length}`);
			cb();
		}
	};
	if (srcArr.length === 0) {
		cb();
		return;
	}
	srcArr.forEach((srcInfo) => {
		let img = new Image();
		img.onload = function () {
			let cdom = srcInfo.dom;
			if ($(cdom).hasClass('ir')) {
				cdom.style.width = img.width + 'rem';
				cdom.style.height = img.height + 'rem';
			}
			doing();
		};
		img.onerror = function () {
			console.error('################ imgLoaded error src is not Found by src = ', img.src);
			doing();
		};
		img.src = srcInfo.src;
	});
}

function getPixelRatio(context) {
	let backingStore =
		context.backingStorePixelRatio || context.webkitBackingStorePixelRatio || context.mozBackingStorePixelRatio || context.msBackingStorePixelRatio || context.oBackingStorePixelRatio || context.backingStorePixelRatio || 1;
	return (window.devicePixelRatio || 1) / backingStore;
}

function createPoster_1_0_0_rc4({ elementId, loading = true, delay = 700, type = 'image/png', quality = 0.7 }) {
	return new Promise((resolve, reject) => {
		setTimeout(() => {
			loading && (app.ajaxLoading = true);
			let posterTmp = document.getElementById(elementId);
			let { width, height } = $(posterTmp).offset();
			var canvas = document.createElement('canvas');
			var context = canvas.getContext('2d');
			var scaleBy = 1; //getPixelRatio(context); //获取像素密度的方法 (也可以采用自定义缩放比例)

			console.log('scaleBy=', scaleBy);
			setTimeout(function () {
				html2canvas(posterTmp, {
					useCORS: true,
					scale: scaleBy,
					width: width,
					height: height,
					backgroundColor: null,
				})
					.then(function (canvas) {
						let url = canvas.toDataURL(type, quality);
						loading && (app.ajaxLoading = false);
						resolve(url);
					})
					.catch((err) => {
						reject(JSON.stringify(err || {}));
					});
			}, 50);
		}, delay);
	});
}

const type_number = 'number';
const type_string = 'string';
const type_boolean = 'boolean';
const type_array = 'array';
const type_object = 'object';
const type_function = 'function';
const type_null = 'null';
const type_undefined = 'undefined';
const type_symbol = 'symbol';
const paramDataTypeDef = {
	[type_number]: '[object Number]',
	[type_string]: '[object String]',
	[type_boolean]: '[object Boolean]',
	[type_array]: '[object Array]',
	[type_object]: '[object Object]',
	[type_function]: '[object Function]',
	[type_null]: '[object Null]',
	[type_undefined]: '[object Undefined]',
	[type_symbol]: '[object Symbol]',
};

function getParamType(param) {
	let type = null;
	for (let key in paramDataTypeDef) {
		if (paramDataTypeDef[key] === Object.prototype.toString.call(param)) {
			type = key;
			break;
		}
	}
	return type;
}

function isFunction(fnc) {
	return !!fnc && getParamType(fnc) === type_function;
}

/**
 * 检测是否不为空对象/空数组
 * @param obj: Object | Array
 */
function isNotNullObject(obj) {
	let type = getParamType(obj);
	if (type === type_object) {
		return !!obj && Object.keys(obj).length > 0;
	} else if (type === type_array) {
		return !!obj && obj.length > 0;
	} else {
		return false;
	}
}

function isNotEmptyString(str) {
	let _str = getParamType(str) === type_number ? str + '' : str;
	return !!_str && !!_str.trim();
}

function isTruePhone(phone, txt) {
	if (!!phone) {
		if (!/^1[3456789]\d{9}$/.test(phone)) {
			//手机号码输入有误
			app.fadeAlert((txt || '联系电话') + '输入有误');
			return false;
		} else {
			return true;
		}
	} else {
		//手机号码未输入
		app.fadeAlert('请输入您的' + (txt || '联系电话'));
		return false;
	}
}

function isIos() {
	var u = navigator.userAgent;
	var isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
	return isIOS;
}

function resetPageScale(width = 750, height = 1334) {
	let ratio = width / height;
	let screen_ratio = screen_width / screen_height;
	log('width', screen_width);
	log('height', screen_height);
	log('ratio', screen_width / screen_height);

	if (screen_ratio > ratio) {
		//小屏(短屏)手机
		let scale = ratio / screen_ratio;
		app.scale = scale;
		log('to scale', scale);
		['transform', '-moz-transform', '-ms-transform', '-o-transform', '-webkit-transform'].forEach((tf) => {
			$('.page_content').css(tf, `scale(${scale})`);
		});
	}
}

function log(title, msg = null) {
	if (!!msg) {
		console.log(`%c ${title} %c %s `, 'background: #35495E;padding: 1px;border-radius: 2px 0 0 2px;color: #fff;', 'background: #409EFF;padding: 1px;border-radius: 0 2px 2px 0;color: #fff;', msg);
	} else {
		console.log(`%c ${title}`, 'background: #35495E;padding: 1px;border-radius: 2px 0 0 2px;color: #fff;');
	}
}

function throttle(fn, interval = 1000) {
	// last为上一次触发回调的时间
	let last = 0;

	// 将throttle处理结果当作函数返回
	return function () {
		// 保留调用时的this上下文
		let context = this;
		// 保留调用时传入的参数
		let args = arguments;
		// 记录本次触发回调的时间
		let now = +new Date();

		// 判断上次触发的时间和本次触发的时间差是否小于时间间隔的阈值
		if (now - last >= interval) {
			// 如果时间间隔大于我们设定的时间间隔阈值，则执行回调
			last = now;
			fn.apply(context, args);
		}
	};
}

function debounce(func, wait = 1000) {
	if (typeof func !== 'function') {
		throw new TypeError('need a function arguments');
	}
	let timeid = null;
	let result;

	return function () {
		let context = this;
		let args = arguments;

		if (timeid) {
			clearTimeout(timeid);
		}
		timeid = setTimeout(function () {
			result = func.apply(context, args);
		}, wait);

		return result;
	};
}

Number.prototype.padLeft = function (len, charStr) {
	let s = this + '';
	let _len = len - s.length + 1;
	_len = _len <= 0 ? 0 : _len;
	return new Array(_len).join(charStr || '') + s;
};
Number.prototype.padRight = function (len, charStr) {
	let s = this + '';
	let _len = len - s.length + 1;
	_len = _len <= 0 ? 0 : _len;
	return s + new Array(_len).join(charStr || '');
};
String.prototype.padLeft = function (len, charStr) {
	let s = this + '';
	let _len = len - s.length + 1;
	_len = _len <= 0 ? 0 : _len;
	return new Array(_len).join(charStr || '') + s;
};
String.prototype.padRight = function (len, charStr) {
	let s = this + '';
	let _len = len - s.length + 1;
	_len = _len <= 0 ? 0 : _len;
	return s + new Array(_len).join(charStr || '');
};

/**
 * 获取手机验证码
 */
let getVeriCodeFac = (function () {
	let v = function () {
		this.getValidateCode_lastTime = 0;
		this.getValidateCode_longTime = 60;
		this.getValidateCode_intervalId = null;
	};
	v.prototype.init = function ({ cla, gettip = '获取获证码', regettip = '重新获取', duration = 60 }, cb = null, cb2 = null) {
		let currTime = +new Date();
		this.getValidateCode_longTime = duration;
		if ((currTime - this.getValidateCode_lastTime) / 1000 >= this.getValidateCode_longTime) {
			this.getValidateCode_lastTime = currTime;
			let btnValidate = $(cla).get(0);
			btnValidate.classList.add('ungetsmscode');
			window.setTimeout(() => {
				btnValidate.classList.remove('btn');
			}, 300);

			let time = this.getValidateCode_longTime;
			$(btnValidate).html(`${regettip}${time}s`);
			this.getValidateCode_intervalId = window.setInterval(() => {
				time--;
				if (time === 0) {
					!!this.getValidateCode_intervalId && window.clearInterval(this.getValidateCode_intervalId);
					$(btnValidate).html(`${gettip}`);
					btnValidate.classList.remove('ungetsmscode');
					btnValidate.classList.add('btn');
					!!cb2 && isFunction(cb2) && cb2();
				} else {
					$(btnValidate).html(`${regettip}${time}s`);
				}
			}, 1000);
			!!cb && isFunction(cb) && cb();
		}
	};
	return new v();
})();

/***
 * 根据秒获取时、分、秒
 * @param time 秒
 * @return [天、时、分、秒]
 */
function getHourMinuteSecond(time = 0) {
	time = !!time ? +time : 0;
	isNaN(time) && (time = 0);
	let oneHourEqSecond = 60 * 60;
	let day = time > 24 * oneHourEqSecond ? ~~(time / (24 * oneHourEqSecond)) : 0;
	let hour = time > oneHourEqSecond ? ~~((time - day * 24 * oneHourEqSecond) / oneHourEqSecond) : 0;
	let minute = time > 60 ? ~~((time - day * 24 * oneHourEqSecond - hour * oneHourEqSecond) / 60) : 0;
	let second = time - day * 24 * oneHourEqSecond - hour * oneHourEqSecond - minute * 60;
	return [day.toFixed(0), hour.toFixed(0), minute.toFixed(0), second.toFixed(0)];
}

let countDownManager = (function () {
	let oManager = {};

	function f() {}

	f.prototype.init = function (id, time, cb) {
		if (Object.keys(oManager).includes(id)) {
			this.clear(id);
		}
		oManager[id] = { intervalId: -1, time: 0 };
		oManager[id].time = time;
		oManager[id].intervalId = window.setInterval(() => {
			if (id in oManager) {
				oManager[id].time--;
				cb(oManager[id].time, oManager[id].intervalId);
				if ((oManager[id]?.time || 0) <= 0) {
					this.clear(id);
				}
			}
		}, 1000);
	};
	f.prototype.clear = function (id) {
		console.log('countDownManager clear interval', id, oManager);
		if (id in oManager) {
			window.clearInterval(oManager[id].intervalId);
			delete oManager[id];
			console.log('clear interval', oManager);
		}
	};
	return new f();
})();

function timeOut(timeLong = 50) {
	return new Promise((resolve, reject) => {
		window.setTimeout(() => {
			resolve();
		}, timeLong);
	});
}

function timeOutPromise(interval = 1000) {
	return new Promise((resolve, reject) => {
		let time = Date.now();

		function f() {
			let currTime = Date.now();
			if (currTime - time >= interval) {
				resolve();
			} else {
				requestAnimationFrame(f);
			}
		}

		requestAnimationFrame(f);
	});
}

Date.prototype.Format = function (fmt) {
	var o = {
		'M+': this.getMonth() + 1, //月份
		'd+': this.getDate(), //日
		'H+': this.getHours(), //小时
		'm+': this.getMinutes(), //分
		's+': this.getSeconds(), //秒
		'q+': Math.floor((this.getMonth() + 3) / 3), //季度
		S: this.getMilliseconds(), //毫秒
	};
	if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + '').substr(4 - RegExp.$1.length));
	for (var k in o) if (new RegExp('(' + k + ')').test(fmt)) fmt = fmt.replace(RegExp.$1, RegExp.$1.length == 1 ? o[k] : ('00' + o[k]).substr(('' + o[k]).length));
	return fmt;
};

function createHeaderByCanvas(imgSrc, w) {
	return new Promise((resolve, reject) => {
		let canvas = document.createElement('canvas');
		$(canvas).css('width', `${w}px`);
		$(canvas).css('height', `${w}px`);

		let avatar = new Image();
		avatar.setAttribute('crossorigin', 'anonymous');
		avatar.src = imgSrc;
		avatar.onload = () => {
			let sw = w * window.devicePixelRatio;
			canvas.width = sw;
			canvas.height = sw;
			circleImg(avatar, 0, 0, sw / 2);
			resolve(canvas.toDataURL('image/png'));
		};

		function circleImg(img, x, y, r) {
			let ctx = canvas.getContext('2d');
			let d = 2 * r;
			let cx = x + r;
			let cy = y + r;
			ctx.arc(cx, cy, r, 0, 2 * Math.PI);
			ctx.clip();
			ctx.drawImage(img, x, y, d, d);
		}
	});
}

function createId(key = '') {
	return window.btoa(encodeURIComponent(key + Date.now() + Math.random().toString(16)));
}

/**
 * 相对地址转绝对地址
 * */
function realativeToAbs(href) {
	let aEl = document.createElement('a');
	aEl.href = href;

	return aEl.href;
}

Promise.prototype.finally = function (cb) {
	let Pro = this.constructor;
	return this.then(
		(val) => Pro.resolve(cb()).then(() => val),
		(reason) =>
			Pro.resolve(cb()).then(() => {
				throw reason;
			})
	);
};

/**
 获取queryString值
 **/
function getQueryString(key) {
	return new URLSearchParams(window.location.search).get(key) || 'undefined';
}

/**
 * 验证提交的数据是否为空
 * @param data 格式：Object/Array ---- { value:值, tip: 为空时对应的提示 }
 * @returns Boolean
 */
function validateIsEmpty(data = null) {
	let isEmpty = false;

	if (!isNotNullObject(data)) {
		return isEmpty;
	}
	let _data = [];
	let t = Object.prototype.toString.call(data);
	if (t === '[object Object]') {
		_data.push(data);
	} else if (t === '[object Array]') {
		_data = data;
	} else {
		return isEmpty;
	}

	if (_data.length > 0) {
		for (info of _data) {
			if (!isNotEmptyString(info.value)) {
				isEmpty = true;
				app.fadeAlert(info.tip || '请输入值');
				break;
			}
		}
	}
	return isEmpty;
}

function shuffle(arr) {
	let i = arr.length;
	while (i) {
		let j = Math.floor(Math.random() * i--);
		[arr[j], arr[i]] = [arr[i], arr[j]];
	}
	return arr;
}

/**
 * 随机出现物品
 * @param goods 格式为对象数组 必须包含rand属性
 * @return good
 */
function randomGood(goods = []) {
	if (!isNotNullObject(goods) || !Array.isArray(goods)) {
		console.error('参数必须为数组');
		return {};
	}
	if (goods.filter((good) => Object.prototype.toString.call(good) === '[object Object]').length !== goods.length) {
		console.error('数组中的每个值必须为对象');
		return {};
	}
	if (goods.filter((good) => good.hasOwnProperty('rand')).length !== goods.length) {
		console.error('数组中的每个对象必须包含rand属性');
		return {};
	}

	let obj;
	let n = 100000;
	let baseNum = Math.floor(Math.abs(Math.random()) * n); // [0, n)

	let gailvBase = [];
	let idx = 0;
	let rands = goods.map(({ rand }) => rand);
	let alls = rands.reduce((prev, curr) => prev + curr, 0);
	// alls = alls < 100 ? 100 : alls;

	goods.forEach((d) => {
		let g = d.rand / alls;
		gailvBase.push(idx == 0 ? Math.ceil(g * n) : Math.ceil(g * n + gailvBase[idx - 1]));
		idx++;
	});
	// console.log('gailvBase = ', gailvBase);

	let idx2 = 0;
	for (let k = 0; k < goods.length; k++) {
		let d = goods[k];
		let isOk = (idx2 == 0 && baseNum < gailvBase[idx2]) || (idx2 > 0 && baseNum >= gailvBase[idx2 - 1] && baseNum < gailvBase[idx2]) ? true : false;
		if (isOk) {
			obj = d;
			break;
		}
		idx2++;
	}

	if (!!!obj) {
		obj = goods[0];
	}

	return obj;
}

function testRandom(goods, randomCount = 100000) {
	if (!isNotNullObject(goods) || !Array.isArray(goods)) {
		console.error('参数必须为数组');
		return;
	}
	if (goods.filter((good) => Object.prototype.toString.call(good) === '[object Object]').length !== goods.length) {
		console.error('数组中的每个值必须为对象');
		return;
	}
	if (goods.filter((good) => good.hasOwnProperty('rand')).length !== goods.length) {
		console.error('数组中的每个对象必须包含rand属性');
		return;
	}

	let tc = randomCount;
	let randoms = {};
	let rands = goods.map(({ rand }) => rand);
	let alls = rands.reduce((prev, curr) => prev + curr, 0);
	for (let i = 0; i < tc; i++) {
		let good = randomGood(goods);
		let { name = encodeURIComponent(JSON.stringify(good)), rand } = good;
		!!randoms[name]
			? ++randoms[name].num
			: (randoms[name] = {
					num: 1,
					rand: `${rand} <-> ${rand}/(${rands.join('+')}=${alls})=${rand / alls}`,
			  });
	}

	console.log('-------------------------');
	console.log(`${tc} random tests`);
	console.log('summary↓↓↓↓↓↓');
	console.log(JSON.stringify(randoms, null, '\t'));
}

function runPromise(promises, defaultValue = '') {
	return promises.reduce((promise, nextPromise) => promise.then((data) => nextPromise(data)), Promise.resolve(defaultValue));
}

function requestIOSPermission(cb) {
	if (isIos()) {
		if (typeof DeviceMotionEvent !== 'undefined' && typeof DeviceMotionEvent.requestPermission === 'function') {
			DeviceMotionEvent.requestPermission()
				.then((response) => {
					if (response == 'granted') {
						cb(1);
					} else {
						console.log('by ${response} 请退出微信后重新进入活动');
						cb(2);
					}
				})
				.catch((err) => {
					console.error(err);
					cb(2);
				});
		} else {
			console.log('DeviceMotionEvent is not defined...');
			cb(2);
		}
	} else {
		cb(1);
	}
}

const mixins = {
	//默认项
	default: {
		data: function () {
			this.audioClickSound = null;
			return {
				isTest: getQueryString('test') == '1',
				loading: true,
				ajaxLoading: false,
				realWidth: 750,
				realHeight: window.innerHeight || window.document.body.clientHeight || window.document.documentElement.clienHeight,

				zIndex: 100,
				pops: [],

				fAlert: {
					show: false,
					text: '提示',
				},
			};
		},
		computed: {
			//
		},
		created() {
			this.audioClickSound = new Howl({ src: `${sysParam.baseUrl}audio/click.mp3${sysParam.version}` });
		},
		mounted() {
			let _this = this;
			document.addEventListener(
				'DOMContentLoaded',
				function () {
					app.showLoadingPage();
					sys.lazyLoad('.body', () => {
						_this.$nextTick(() => {
							//加载完毕
							sys.loadingComplete();

							resetPageScale(this.width, this.height);
							window.setTimeout(() => {
								resetPageScale(this.width, this.height);
							}, 50);

							$('input').on('blur', function () {
								document.activeElement.scrollIntoViewIfNeeded(true);
								document.activeElement.scrollIntoView();
								console.log('input blur...');
							});

							$('#app').on('click', '.effect', function (e) {
								_this.audioClickSound && _this.audioClickSound.play();
							});

							log('initEnd...');
							!!_this.initEnd && _this.initEnd();
						});
					});
				},
				false
			);
		},
		methods: {
			initLazyLoad(id, cb = null) {
				!!!this.page[id] && (this.ajaxLoading = true);
				this[id]?.hasOwnProperty('key') && (this[id].key = createId(id));
				this.$nextTick(() => {
					lazyLoad(`.${id} .lazy`, () => {
						!!!this.page[id] && (this.ajaxLoading = false);

						if (this.scroll[id]) {
							window.setTimeout(() => {
								this.scroll[id].refresh();
								this.scroll[id].scrollTo(0, 0);
							}, 200);
						}
						!!cb && cb();
					});
				});
			},

			clearTime(timeoutId) {
				timeoutId && window.clearTimeout(timeoutId);
			},

			clearInterval(intervalId) {
				intervalId && window.clearInterval(intervalId);
			},

			isShowPop(popName) {
				return this.pops.includes(popName) || false;
			},

			//切换页面
			pageShow(id, cb = null) {
				this.initLazyLoad(id, () => {
					for (let i in this.page) {
						this.page[i] = i == id ? true : false;
					}
					gsap.set(`.page`, { autoAlpha: 0 });
					gsap.set(`.page.${id}`, {
						duration: 0.5,
						autoAlpha: 1,
						onComplete() {
							isFunction(cb) && cb();
						},
					});
				});
			},

			//弹窗切换
			popShow(id, isMultiPop = false, cb = null) {
				if ($(`.pop.${id}`).length === 0) {
					isFunction(cb) && cb();
					return;
				}
				let isExists = app.pops.includes(id);
				this.initLazyLoad(id, () => {
					if (!isExists) {
						if (!isMultiPop) {
							//只存在一级弹窗
							this.closeAll();
						}
						gsap.set(`.pop.${id}`, { 'z-index': ++this.zIndex });

						this.popShowPop(id, cb);
					} else {
						isFunction(cb) && cb();
					}
				});
			},

			popShowPop(id = null, cb = null) {
				this.pops.push(id);
				let popContentClass = `.pop.${id} .pop_content`;
				gsap.set(`.pop.${id}`, {
					autoAlpha: 1,
				});

				if ($(popContentClass).length > 0) {
					let delay = 0;
					let classBorder = `.pop.${id} .border_anim`;
					let isHaveBorderStyle = $(classBorder).length > 0;
					if (isHaveBorderStyle) {
						gsap.set(popContentClass, popIn);
						let { width, height } = $(popContentClass).offset();
						let $border = $(classBorder);
						$border.css('width', width + 'px').css('height', height + 'px');
						$border.addClass('run');
						delay = 0.3 + 0.1;
					}
					gsap.set(popContentClass, popFrom);
					gsap.to(popContentClass, {
						...popIn,
						duration: 0.3,
						delay,
						ease: 'ease.in',
						onStart() {},
						onComplete() {
							if (isHaveBorderStyle) {
								$(classBorder).removeClass('run');
							}
							if (gsap.utils.selector(`.pop.${id}`)('.btn_close').length > 0) {
								let isConfirm = gsap.utils.selector(`.pop.${id}`)('.btn_close.confirm').length > 0;
								gsap.set(`.pop.${id} .btn_close`, Object.assign({ scaleX: 0, scaleY: 0 }, isConfirm ? {} : { rotation: -180 }));
								gsap.to(
									`.pop.${id} .btn_close`,
									Object.assign(
										{
											duration: 0.5,
											autoAlpha: 1,
											scaleX: 1,
											scaleY: 1,
										},
										isConfirm ? {} : { rotation: 0 }
									)
								);
							}
							isFunction(cb) && cb();
						},
					});
				} else {
					isFunction(cb) && cb();
				}
			},

			//关闭弹窗
			close(cb = null) {
				let id = this.pops.pop();
				this.closePop(id, cb);
				if (this.pops.length == 0) {
					this.zIndex = 100;
				}
			},

			closeAll() {
				let popId = app.pops.pop();
				while (popId) {
					this.closePop(popId);
					popId = app.pops.pop();
				}
				this.zIndex = 100;
			},

			closePop(id = null, cb = null) {
				if (!isNotEmptyString(id)) {
					isFunction(cb) && cb();
					return;
				}
				gsap.utils.selector(`.pop.${id}`)('.btn_close').length > 0 && gsap.set(`.pop.${id} .btn_close`, { autoAlpha: 0 });
				let finishedFn = () => {
					gsap.to(`.pop.${id}`, {
						autoAlpha: 0,
						duration: 0.5,
						onComplete() {
							isFunction(cb) && cb();
						},
					});
				};

				let popContentClass = `.pop.${id} .pop_content`;
				if ($(popContentClass).length > 0) {
					gsap.to(popContentClass, {
						...popOut,
						duration: 0.3,
						ease: 'none',
						onComplete() {
							finishedFn();
						},
					});
				} else {
					finishedFn();
				}
			},

			// 错误提示淡入淡出
			fadeAlert: function (text, time) {
				if (this.fadeAlertSetTime) {
					clearTimeout(this.fadeAlertSetTime);
				}
				this.fAlert.show = true;
				this.fAlert.text = text;
				this.fadeAlertSetTime = setTimeout(
					function () {
						app.fAlert.show = false;
					},
					time ? time : 2500
				);
			},

			//跳转外链
			goUrl: function (url) {
				window.location.href = url;
			},
			//替换当前页
			replaceUrl: function (url) {
				window.location.replace(url);
			},
			next() {
				return new Promise((resolve) => {
					this.$nextTick(resolve);
				});
			},
		},
	},
};

function loadJS(name, cb = null) {
	let scr = document.createElement('script');
	scr.type = 'text/javascript';
	scr.onload = function () {
		console.log('loadJS success', name);
		isFunction(cb) && cb();
	};
	scr.src = name;
	document.body.appendChild(scr);
}

function truncNumber(_num = 0, isDown = true) {
	let num = !isDown ? Math.ceil(_num) : Math.floor(_num);
	if (num % 2 != 0) {
		num = !isDown ? num + 1 : num - 1;
	}
	return num;
}

(function () {
	if (getQueryString('console') == 1) {
		loadJS('https://res1.i-lz.cn/static/common/vconsole.min.js', () => {
			new VConsole();
		});
	}
})();

(function () {
	if (!!!window.structuredClone) {
		window.structuredClone = function (data) {
			return JSON.parse(JSON.stringify(data));
		};
	}
})();

(function () {
	let imgs = $('#app img');
	imgs.forEach((img) => {
		$(img).attr('draggable', false);
		$('#app .poster img').attr('crossOrigin', 'anonymous');
	});

	Vue.directive('pop', {
		update(el, binding) {
			el.style.display = (app.pops || []).includes(binding.value) ? '' : 'none';
		},
	});

	Vue.directive('left', {
		inserted(el, binding) {
			let val = +(binding.value || 0);
			let ah = (app || {}).height;
			let rh = (app || {}).realHeight;
			el.style.left = truncNumber((val / ah) * rh) + 'rem';
		},
		update(el, binding) {
			let val = +(binding.value || 0);
			let ah = (app || {}).height;
			let rh = (app || {}).realHeight;
			el.style.left = truncNumber((val / ah) * rh) + 'rem';
		},
	});

	Vue.directive('lefty', {
		inserted(el, binding) {
			el.style.left = truncNumber(+(binding.value || 0)) + 'rem';
		},
		update(el, binding) {
			el.style.left = truncNumber(+(binding.value || 0)) + 'rem';
		},
	});

	Vue.directive('top', {
		inserted(el, binding) {
			let val = +(binding.value || 0);
			let ah = (app || {}).height;
			let rh = (app || {}).realHeight;
			el.style.top = (val / ah) * 100 + '%';
		},
		update(el, binding) {
			let val = +(binding.value || 0);
			let ah = (app || {}).height;
			let rh = (app || {}).realHeight;
			el.style.top = (val / ah) * 100 + '%';
		},
	});

	Vue.directive('topy', {
		inserted(el, binding) {
			el.style.top = truncNumber(+(binding.value || 0)) + 'rem';
		},
		update(el, binding) {
			el.style.top = truncNumber(+(binding.value || 0)) + 'rem';
		},
	});

	Vue.directive('bg', {
		inserted(el, binding) {
			el.style.backgroundImage = `url(${binding.value})`;
		},
		update(el, binding) {
			el.style.backgroundImage = `url(${binding.value})`;
		},
	});

	Vue.component('mytext', {
		template: `
        <div class="inline_block">
            <template v-if="loading">加载中<dot></dot></template>
            <template v-else>{{value}}</template>
        </div>
        `,
		props: ['loading', 'value'],
	});
})();

function forceLandscape(selector = null) {
	const handler = () => {
		if (!!!selector) {
			return;
		}
		let width = appWidth;
		let height = appHeight;
		let targetDom = document.querySelector(selector);
		if (!targetDom) return;

		// 如果宽度比高度大，则认为处于横屏状态
		// 也可以获取 window.orientation 方向来判断屏幕状态
		if (width > height) {
			targetDom.style.position = 'absolute';
			targetDom.style.width = `${width}px`;
			targetDom.style.height = `${height}px`;
			targetDom.style.left = `${0}px`;
			targetDom.style.top = `${0}px`;
			targetDom.style.transform = 'none';
			targetDom.style.transformOrigin = '50% 50%';
		} else {
			targetDom.style.position = 'absolute';
			targetDom.style.width = `${height}px`;
			targetDom.style.height = `${width}px`;
			targetDom.style.left = `${0 - (height - width) / 2}px`;
			targetDom.style.top = `${(height - width) / 2}px`;
			targetDom.style.transform = 'rotate(90deg)';
			targetDom.style.transformOrigin = '50% 50%';
		}
	};

	const handleResize = () => {
		setTimeout(() => {
			handler();
		}, 300);
	};

	window.addEventListener('resize', handleResize);

	handler();
}

(function () {
	CanvasRenderingContext2D.prototype.wrapText = function (text, x, y, maxWidth, lineHeight) {
		if (typeof text != 'string' || typeof x != 'number' || typeof y != 'number') {
			return;
		}

		var context = this;
		var canvas = context.canvas;

		if (typeof maxWidth == 'undefined') {
			maxWidth = (canvas && canvas.width) || 300;
		}
		if (typeof lineHeight == 'undefined') {
			lineHeight = (canvas && parseInt(window.getComputedStyle(canvas).lineHeight)) || parseInt(window.getComputedStyle(document.body).lineHeight);
		}

		// 字符分隔为数组
		var arrText = text.split('');
		var line = '';

		for (var n = 0; n < arrText.length; n++) {
			var testLine = line + arrText[n];
			var metrics = context.measureText(testLine);
			var testWidth = metrics.width;
			if (testWidth > maxWidth && n > 0) {
				context.fillText(line, x, y);
				line = arrText[n];
				y += lineHeight;
			} else {
				line = testLine;
			}
		}
		context.fillText(line, x, y);
	};
})();
